package com.raymond.netty;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.util.concurrent.DefaultEventExecutorGroup;
import io.netty.util.concurrent.EventExecutorGroup;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

/**
 * netty启动类
 *
 * @author :  raymond
 * @version :  1.0
 * @date :  2020/06/18
 */
@Component
@Slf4j
public class NettyStart {

    @Value("${netty.port}")
    private Integer port;

    public NioEventLoopGroup parent;

    public NioEventLoopGroup child;

    private final ServerInitializer serverInitializer;

    public NettyStart(ServerInitializer serverInitializer) {
        this.serverInitializer = serverInitializer;
    }


    @Async
    public void init() {
        log.info("启动netty服务中,端口:{}", port);
        int processors = Runtime.getRuntime().availableProcessors();

        parent = new NioEventLoopGroup(2);
        child = new NioEventLoopGroup();
        EventExecutorGroup executorGroup = new DefaultEventExecutorGroup(processors * 2);
        ServerBootstrap bootstrap = new ServerBootstrap();
        bootstrap.group(parent, child).channel(NioServerSocketChannel.class)
                .handler(new LoggingHandler(LogLevel.INFO))
                //标识当服务器请求处理线程全满时，用于临时存放已完成三次握手的请求的队列的最大长度 默认值50
                .option(ChannelOption.SO_BACKLOG, 1024 * 5)
                .option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
                //关键是这句
                .childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
                .childOption(ChannelOption.SO_KEEPALIVE, false)
                //初始化pipeline
                .childHandler(serverInitializer);

        //绑定接口，优雅关闭
        try {
            log.info("启动netty服务成功");
            bootstrap.bind(port).sync().channel().closeFuture().sync();
        } catch (Exception e) {
            log.error("启动netty服务异常", e);
        } finally {
            //优雅退出，释放线程池资源
            parent.shutdownGracefully();
            child.shutdownGracefully();
        }
    }


}
